#pragma once
#include <stdio.h>
#include <unistd.h>
#include <boost/mpl/size_t.hpp>
#include <layout.hpp>
#include <findblock.hpp>

namespace raw {
using namespace usrtos;
using namespace std;

template<size_t AT, size_t END>
class Raw : public Mem<AT> {
public:
    const size_t _AT  = AT;
    const size_t _END = END;

    typedef Mem<AT> memtype;
	typedef boost::mpl::size_t<((END-AT-sizeof(typename Mem<AT>::bar)-16)/sizeof(size_t))> DATASIZE;
		
	struct data_addons : memtype::bar {
		size_t buf[DATASIZE::value];
	};


private:
	CPBlock *m_mem;
	struct data_addons* m_pd;

public:
    Raw() : Mem<AT>() {};
	Raw(CPBlock& m) : Mem<AT>(m){
		m_mem = &m;
		m_pd = static_cast<struct data_addons*>((void *)((char *)m_mem->getHead()+AT));
	};
	
	CPBlock *getMem() { return m_mem; };

    void *getAppdata() { return (void *)&(m_pd->buf);};

	size_t getPos() { return m_pd->pos; };
	void setPos(size_t pos) { 
        USRT_SCOPED_LOCK(m_pd->bar_mutex);
        m_pd->pos = pos;
    };

    void dumpHead() { 
        m_mem->dump();
        Mem<AT>::dump();
    };

    template<typename T>
    void write(T *in,size_t len) {
        T *m = Mem<AT>::template newLP<T>(len);
        memcpy(m,in,len*sizeof(T));
	};

    inline void *getBuf(uint64_t from) {
        return (void *)m_mem->Off2LP<char>(from);
    };

    int reset() { return 0; };

};

}; // end namespace raw
